home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / set.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  36.2 KB  |  1,222 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/set.c,v 2.9 90/10/04 18:26:40 melissa Exp $";
  10. #endif
  11.  
  12. /*
  13.  * set.c - support for the "set" command
  14.  *
  15.  * All the internal variables which can be explicitly changed by the
  16.  * user are declared here, along with the code implementing the "set" 
  17.  * command itself.
  18.  */
  19.  
  20. #include "mm.h"
  21. #include "parse.h"
  22. #include "set.h"
  23. #include "cmds.h"
  24.  
  25. #define CHAR_SQ '\''            /* \047 */
  26. #define CHAR_BS '\\'            /* \0134 */
  27.  
  28. #define isquote(x) (x == CHAR_SQ)
  29. #define isbackslash(x) (x == CHAR_BS)
  30.  
  31.  
  32. extern char **parse_filelist();
  33. char *show_filename();
  34.  
  35. int    aliases_use_groups = SET_NO,    /* aliases != groups */
  36.         append_new_mail = SET_NO,       /* use old style fetchmail() */
  37.         append_signature = SET_NO,    /* don't append .signature file */
  38.     auto_create_files = SET_ASK,    /* ask about new files */
  39.     auto_startup_get = SET_YES,    /* get your mailfile on startup */
  40.         autowrap_column,        /* set up in initialize */
  41.     browse_clear_screen = SET_YES,    /* clear before showing each header */
  42.         browse_pause = SET_YES,        /* pause between messages on browse */
  43.       check_interval = 300,        /* interval for newmail alarm() */
  44.         clear_screen = SET_YES,        /* clear screen by default */
  45.         continuous_check = SET_NO,    /* check constantly for new mail */
  46.         control_d_automatic_send = SET_NO, /* don't send automatically on ^D */
  47.     control_e_editor = SET_YES,    /* ^E invokes editor */
  48.         control_l_confirm = SET_NO,    /* don't confirm on ^L */
  49.     control_n_abort = SET_ASK,    /* ask about abort */
  50.     directory_folders = SET_NO,    /* can folders be directories */
  51.     display_flagged_messages = SET_YES, /* show flagged messages */
  52.       display_outgoing_message = SET_NO, /* show msg when prompting */
  53.         escape_automatic_send = SET_NO,    /* send automatically on esc */
  54.     expunge_on_bye = SET_ASK,    /* expunge when they say bye */
  55.     fast_init_file = SET_YES,    /* use fast init file */
  56.       gnuemacs_mmail = SET_YES,    /* we have gnuemacs mmail mode */
  57.         handle_changed_modtime = SET_YES, /* recover from mtime change */
  58.       list_include_headers = SET_YES,    /* put index before messages */
  59.       list_on_separate_pages = SET_NO, /* don't put formfeed between msgs */
  60.         modify_read_only = SET_YES,    /* don't ask whether to modify */
  61.     new_file_mode = 0600,        /* default mode */
  62.     prompt_for_bcc = SET_NO,    /* prompt for bcc on send */
  63.     prompt_for_cc = SET_YES,    /* prompt for cc on send */
  64.     prompt_for_fcc = SET_NO,    /* prompt for fcc on send */
  65.         prompt_rcpt_always = SET_NO;    /* prompt even when "send foo" */
  66.     reply_all = SET_NO,        /* don't reply to everyone */
  67.         reply_include_me = SET_NO,    /* replies go to self too */
  68.         reply_initial_display = SET_NO,    /* display To, Cc, etc when replying */
  69.     reply_insert = SET_NO,        /* don't include original in reply */
  70.       send_verbose = SET_YES,        /* show all recipients when sending */
  71.       sendmail_verbose = SET_NO,    /* don't be verbose when sending */
  72.       sendmail_background = SET_YES,    /* Send mail in the background */
  73.         suspend_on_exit = SET_NO,    /* suspend when a quit is done */
  74.         suspend_on_quit = SET_NO,    /* suspend when a quit is done */
  75.         terse_text_prompt = SET_NO,    /* don't be terse when prompting */
  76.     use_editor_always = SET_NO,    /* don't use the editor by default */
  77.         use_crt_filter_always = SET_NO;    /* don't always filter things */
  78.     use_invalid_address = SET_ASK;    /* ask about invalid addresses */
  79.  
  80. string    crt_filter = { PAGER },
  81.         default_from = { NULL },
  82.       default_read_command = { "next" },
  83.     default_reply_to = { NULL },
  84.       default_send_command = { NULL },
  85.         finger_command = { "finger" },
  86.       header_options_file = { "/dev/null" },
  87.       help_file = { HELPFILE },
  88.       help_dir = { HELPDIR },
  89.     mail_directory = { "." },
  90.     mail_file = { NULL},
  91.         mmail_path = { MMAIL_PATH },
  92.       movemail_path = { MOVEMAIL },
  93.     personal_name = { 0 },
  94.         print_filter = { "lpr" },
  95.     read_prompt = { "R>" },
  96.     reply_indent = { "> " },
  97.     saved_messages_file = { "/dev/null" },
  98.     send_prompt = { "S>" },
  99.       temp_directory = { NULL },    /* set in init.c:initialize() */
  100.     top_level_prompt = { "MM>" },
  101.         user_name = { NULL };
  102.  
  103. addresslist
  104.     default_bcc_list = { nil, nil },
  105.     default_cc_list = { nil, nil };
  106.  
  107. keylist    dont_print_headers = nil,
  108.         dont_type_headers = nil,
  109.     user_keywords = nil,
  110.         only_print_headers = nil,
  111.     only_type_headers = nil,
  112.     user_headers = nil,
  113.     incoming_mail = nil,
  114.       editor = NULL,
  115.     default_fcc_list = nil,
  116.         speller = NULL;
  117.  
  118.  
  119.  
  120. extern Mail_aliases mail_aliases;
  121.  
  122. keywrd user_levels[] = {
  123.     { "novice", 0, NOVICE },
  124.     { "expert", 0, EXPERT },
  125. };
  126.  
  127. keytab user_levtab = { sizeof(user_levels) / sizeof(keywrd), user_levels };
  128. fdb user_level_fdb = { _CMKEY, 0, nil, (pdat) &user_levtab, "user level" };
  129.  
  130. extern keytab send_keytab, read_keytab;
  131. setkey default_mail_type = { &formattab, "mbox" },
  132.        user_level = { &user_levtab, "expert" };
  133.  
  134.  
  135. keywrd set_cmds[] = {
  136.     { "aliases-use-groups",    0, (keyval) SET_ALIASES_USE_GROUPS },
  137.     { "append-new-mail",        0, (keyval) SET_APPEND_NEW_MAIL },
  138.     { "append-signature",    0, (keyval) SET_APPEND_SIGNATURE },
  139.     { "auto-create-files",    0, (keyval) SET_AUTO_CREATE_FILES },
  140.     { "auto-startup-get",     0, (keyval) SET_AUTO_STARTUP_GET },
  141.     { "autowrap-column",     0, (keyval) SET_AUTOWRAP_COLUMN },
  142.     { "browse-clear-screen",    0, (keyval) SET_BROWSE_CLEAR_SCREEN },
  143.     { "browse-pause",         0, (keyval) SET_BROWSE_PAUSE },
  144.     { "check-interval",        0, (keyval) SET_CHECK_INTERVAL },
  145.     { "clear-screen",         0, (keyval) SET_CLEAR_SCREEN },
  146.     { "continuous-check",    0, (keyval) SET_CONTINUOUS_CHECK },
  147.     { "control-d-automatic-send", 0, (keyval) SET_CONTROL_D_AUTOMATIC_SEND },
  148.     { "control-e-editor",     0, (keyval) SET_CONTROL_E_EDITOR },
  149.     { "control-l-confirm",     0, (keyval) SET_CONTROL_L_CONFIRM },
  150.     { "control-n-abort",     0, (keyval) SET_CONTROL_N_ABORT },
  151.     { "crt-filter",         0, (keyval) SET_CRT_FILTER },
  152.     { "default-bcc-list",    0, (keyval) SET_DEFAULT_BCC_LIST },
  153.     { "default-cc-list",    0, (keyval) SET_DEFAULT_CC_LIST },
  154.     { "default-fcc-list",    0, (keyval) SET_DEFAULT_FCC_LIST },
  155.     { "default-from",        0, (keyval) SET_DEFAULT_FROM },
  156.     { "default-mail-type",    0, (keyval) SET_DEFAULT_MAIL_TYPE },
  157.     { "default-read-command",    0, (keyval) SET_DEFAULT_READ_COMMAND },
  158.     { "default-reply-to",    0, (keyval) SET_DEFAULT_REPLY_TO },
  159.     { "default-send-command",    0, (keyval) SET_DEFAULT_SEND_COMMAND },
  160.     { "directory-folders",    0, (keyval) SET_DIRECTORY_FOLDERS },
  161.     { "display-flagged-messages",0, (keyval) SET_DISPLAY_FLAGGED_MESSAGES },
  162.     { "display-outgoing-message",0, (keyval) SET_DISPLAY_OUTGOING_MESSAGE },
  163.     { "dont-print-headers",    0, (keyval) SET_DONT_PRINT_HEADERS },
  164.     { "dont-type-headers",     0, (keyval) SET_DONT_TYPE_HEADERS },
  165.     { "editor",             0, (keyval) SET_EDITOR },
  166.     { "escape-automatic-send",    0, (keyval) SET_ESCAPE_AUTOMATIC_SEND },
  167.     { "expunge-on-bye",        0, (keyval) SET_EXPUNGE_ON_BYE },
  168.     { "fast-init-file",        0, (keyval) SET_FAST_INIT_FILE },
  169.     { "finger-command",        0, (keyval) SET_FINGER_COMMAND },
  170.     { "gnuemacs-mmail",        0, (keyval) SET_GNUEMACS_MMAIL },
  171.     { "handle-changed-modtime", KEY_INV, (keyval) SET_HANDLE_CHANGED_MODTIME },
  172.     { "header-options-file",     0, (keyval) SET_HEADER_OPTIONS_FILE },
  173.     { "help-file",      KEY_INV, (keyval) SET_HELP_FILE },
  174.     { "help-dir",      KEY_INV, (keyval) SET_HELP_DIR },
  175.     { "incoming-mail",         0, (keyval) SET_INCOMING_MAIL },
  176.     { "keywords",         0, (keyval) SET_KEYWORDS },
  177.     { "list-include-headers",    0, (keyval) SET_LIST_INCLUDE_HEADERS },
  178.     { "list-on-separate-pages", 0, (keyval) SET_LIST_ON_SEPARATE_PAGES },
  179.     { "mail-aliases",           0, (keyval) SET_MAIL_ALIASES },
  180.     { "mail-directory",     0, (keyval) SET_MAIL_DIRECTORY },
  181.     { "mail-file",         0, (keyval) SET_MAIL_FILE },
  182.     { "mmail-path",      KEY_INV, (keyval) SET_MMAIL_PATH },
  183.     { "modify-read-only",    0, (keyval) SET_MODIFY_READ_ONLY },
  184.     { "movemail-path",      KEY_INV, (keyval) SET_MOVEMAIL_PATH },
  185.     { "new-file-mode",         0, (keyval) SET_NEW_FILE_MODE },
  186.     { "only-print-headers",    0, (keyval) SET_ONLY_PRINT_HEADERS },
  187.     { "only-type-headers",     0, (keyval) SET_ONLY_TYPE_HEADERS },
  188.     { "personal-name",         0, (keyval) SET_PERSONAL_NAME },
  189.     { "print-filter",         0, (keyval) SET_PRINT_FILTER },
  190.     { "prompt-for-bcc",     0, (keyval) SET_PROMPT_FOR_BCC },
  191.     { "prompt-for-cc",         0, (keyval) SET_PROMPT_FOR_CC },
  192.     { "prompt-for-fcc",     0, (keyval) SET_PROMPT_FOR_FCC },
  193.     { "prompt-rcpt-always",    0, (keyval) SET_PROMPT_RCPT_ALWAYS },
  194.     { "read-prompt",         0, (keyval) SET_READ_PROMPT },
  195.     { "reply-all",         0, (keyval) SET_REPLY_ALL },
  196.     { "reply-include-me",    0, (keyval) SET_REPLY_INCLUDE_ME },
  197.     { "reply-indent",         0, (keyval) SET_REPLY_INDENT },
  198.     { "reply-initial-display",    0, (keyval) SET_REPLY_INITIAL_DISPLAY },
  199.     { "reply-insert",         0, (keyval) SET_REPLY_INSERT },
  200.     { "saved-messages-file",     0, (keyval) SET_SAVED_MESSAGES_FILE },
  201.     { "send-prompt",         0, (keyval) SET_SEND_PROMPT },
  202.     { "send-verbose",        0, (keyval) SET_SEND_VERBOSE },
  203.     { "sendmail-background",    0, (keyval) SET_SENDMAIL_BACKGROUND },
  204.     { "sendmail-verbose",    0, (keyval) SET_SENDMAIL_VERBOSE },
  205.     { "speller",        0, (keyval) SET_SPELLER },
  206.     { "suspend-on-exit",     0, (keyval) SET_SUSPEND_ON_EXIT },
  207.     { "suspend-on-quit",     0, (keyval) SET_SUSPEND_ON_QUIT },
  208.     { "temp-directory",        0, (keyval) SET_TEMP_DIRECTORY },
  209.     { "terse-text-prompt",    0, (keyval) SET_TERSE_TEXT_PROMPT },
  210.     { "top-level-prompt",     0, (keyval) SET_TOP_LEVEL_PROMPT },
  211.     { "use-crt-filter-always",    0, (keyval) SET_USE_CRT_FILTER_ALWAYS },
  212.     { "use-editor-always",     0, (keyval) SET_USE_EDITOR_ALWAYS },
  213.     { "use-invalid-address",     0, (keyval) SET_USE_INVALID_ADDRESS },    
  214.     { "user-headers",         0, (keyval) SET_USER_HEADERS },
  215.     { "user-level",        0, (keyval) SET_USER_LEVEL },
  216.     { "user-name",        0, (keyval) SET_USER_NAME },
  217. };
  218.  
  219. keytab set_keytab = { sizeof (set_cmds) / sizeof (keywrd), set_cmds };
  220. fdb set_cmd_fdb = { _CMKEY, 0, nil, (pdat) &set_keytab, "variable, " };
  221.  
  222. /*
  223.  * The following structure is a gross hack, since all of the variable
  224.  * addresses are coerced to (char *) and back.  Need to rewrite someday.
  225.  *
  226.  * Anyway, the purpose is to encode in a single structure the name of
  227.  * the variable, it's address, size, and a brief description, to make
  228.  * it easy to set/dump all the variables, etc.
  229.  */
  230. #ifdef __STDC__
  231. #define XXs(name, type) VAR_##type,           name, sizeof (name)
  232. #define  XX(name, type) VAR_##type, (char *) &name, sizeof (name)
  233. #else
  234. #define XXs(name, type) VAR_/**/type,           name, sizeof (name)
  235. #define  XX(name, type) VAR_/**/type, (char *) &name, sizeof (name)
  236. #endif
  237.  
  238. variable set_variables[] = {
  239.     { "aliases-use-groups", XX(aliases_use_groups,BOOLEAN)},
  240.     { "append-new-mail", XX(append_new_mail,BOOLEAN)},
  241.     { "append-signature", XX(append_signature,MAYBE)},
  242.     { "auto-create-files", XX(auto_create_files,MAYBE)},
  243.     { "auto-startup-get", XX(auto_startup_get,BOOLEAN)},
  244.     { "autowrap-column", XX(autowrap_column,INTEGER)},
  245.     { "browse-clear-screen", XX(browse_clear_screen,BOOLEAN)},
  246.     { "browse-pause", XX(browse_pause,BOOLEAN)},
  247.     { "check-interval", XX(check_interval,INTEGER)},
  248.     { "clear-screen", XX(clear_screen,BOOLEAN)},
  249.     { "continuous-check", XX(continuous_check,BOOLEAN)},
  250.     { "control-d-automatic-send", XX(control_d_automatic_send,BOOLEAN)},
  251.     { "control-e-editor", XX(control_e_editor,BOOLEAN)},
  252.     { "control-l-confirm", XX(control_l_confirm,BOOLEAN)},
  253.     { "control-n-abort", XX(control_n_abort,MAYBE)},
  254.     { "crt-filter", XXs(crt_filter,COMMAND)},
  255.     { "default-bcc-list", XX(default_bcc_list,ADDRLIST)},
  256.     { "default-cc-list", XX(default_cc_list,ADDRLIST)},
  257.     { "default-fcc-list", XX(default_fcc_list,FILES)},
  258.     { "default-from", XXs(default_from,TEXT)},
  259.     { "default-mail-type", XX(default_mail_type,KEYWORDS)},
  260.     { "default-read-command", XXs(default_read_command,CMDKEYS)},
  261.     { "default-reply-to", XXs(default_reply_to,TEXT)},
  262.     { "default-send-command", XXs(default_send_command,CMDKEYS)},
  263.     { "directory-folders", XX(directory_folders,BOOLEAN)},
  264.     { "display-flagged-messages", XX(display_flagged_messages,BOOLEAN)},
  265.     { "display-outgoing-message", XX(display_outgoing_message,BOOLEAN)},
  266.     { "dont-print-headers", XX(dont_print_headers,KEYLIST)},
  267.     { "dont-type-headers", XX(dont_type_headers,KEYLIST)},
  268.     { "editor", XX(editor,CMDARGS)},
  269.     { "escape-automatic-send",    XX(escape_automatic_send,BOOLEAN)},
  270.     { "expunge-on-bye", XX(expunge_on_bye,MAYBE)},
  271.     { "fast-init-file", XX(fast_init_file,MAYBE)},
  272.     { "finger-command", XXs(finger_command,COMMAND)},
  273.     { "gnuemacs-mmail", XX(gnuemacs_mmail,BOOLEAN)},
  274.     { "handle-changed-modtime", XX(handle_changed_modtime,MAYBE)},
  275.     { "header-options-file", XXs(header_options_file,FILE)},
  276.     { "help-file", XXs(help_file,FILE)},
  277.     { "help-dir", XXs(help_dir,DIRECTORY)},
  278.     { "incoming-mail", XX(incoming_mail,FILES)},
  279.     { "keywords", XX(user_keywords,KEYLIST)},
  280.     { "list-include-headers", XX(list_include_headers,BOOLEAN)},
  281.     { "list-on-separate-pages", XX(list_on_separate_pages,BOOLEAN)},
  282.     { "mail-aliases", XX(mail_aliases,ALIAS)},
  283.     { "mail-directory", XXs(mail_directory,DIRECTORY)},
  284.     { "mail-file", XXs(mail_file,OFILE)},
  285.     { "mmail-path", XXs(mmail_path,FILE)},
  286.     { "modify-read-only", XX(modify_read_only,MAYBE)},
  287.     { "movemail-path", XXs(movemail_path,COMMAND)},
  288.     { "new-file-mode", XX(new_file_mode,INTEGER)},
  289.     { "only-print-headers", XX(only_print_headers,KEYLIST)},
  290.     { "only-type-headers", XX(only_type_headers,KEYLIST)},
  291.     { "personal-name", XXs(personal_name,TEXT)},
  292.     { "print-filter", XXs(print_filter,COMMAND)},
  293.     { "prompt-for-bcc", XX(prompt_for_bcc,BOOLEAN)},
  294.     { "prompt-for-cc", XX(prompt_for_cc,BOOLEAN)},
  295.     { "prompt-for-fcc", XX(prompt_for_fcc,BOOLEAN)},
  296.     { "prompt-rcpt-always", XX(prompt_rcpt_always ,BOOLEAN)},
  297.     { "read-prompt", XXs(read_prompt,PROMPT)},
  298.     { "reply-all", XX(reply_all,BOOLEAN)},
  299.     { "reply-include-me", XX(reply_include_me,BOOLEAN)},
  300.     { "reply-indent", XXs(reply_indent,QUOTEDSTR)},
  301.     { "reply-initial-display", XX(reply_initial_display,BOOLEAN)},
  302.     { "reply-insert", XX(reply_insert,BOOLEAN)},
  303.     { "saved-messages-file", XXs(saved_messages_file,OFILE)},
  304.     { "send-prompt", XXs(send_prompt,PROMPT)},
  305.     { "send-verbose", XX(send_verbose,BOOLEAN)},
  306.     { "sendmail-background", XX(sendmail_background,BOOLEAN)},
  307.     { "sendmail-verbose", XX(sendmail_verbose,BOOLEAN)},
  308.     { "speller", XX(speller,CMDARGS)},
  309.     { "suspend-on-exit", XX(suspend_on_exit,BOOLEAN)},
  310.     { "suspend-on-quit", XX(suspend_on_quit,BOOLEAN)},
  311.     { "temp-directory", XXs(temp_directory,DIRECTORY)},
  312.     { "terse-text-prompt", XX(terse_text_prompt,BOOLEAN)},
  313.     { "top-level-prompt", XXs(top_level_prompt,PROMPT)},
  314.     { "use-crt-filter-always", XX(use_crt_filter_always,BOOLEAN)},
  315.     { "use-editor-always", XX(use_editor_always,BOOLEAN)},
  316.     { "use-invalid-address", XX(use_invalid_address,MAYBE)},
  317.     { "user-headers", XX(user_headers,KEYLIST)},
  318.     { "user-level", XX(user_level,KEYWORDS)},
  319.     { "user-name", XXs(user_name,USERNAME)},
  320. };
  321. #undef XX
  322. #undef XXs
  323.  
  324. int set_variable_count = sizeof (set_variables) / sizeof (set_variables[0]);
  325.  
  326. int
  327. set_variable (n)
  328. int n;
  329. {
  330.     int x;
  331.     char *p, **q;
  332.     char **ap;
  333.     variable *v = &set_variables[n];
  334.     caddr_t dangling = 0;
  335.     char **split_args();
  336.  
  337.     switch (v->type) {
  338.       case VAR_BOOLEAN:
  339.     x = parse_yesno ("yes");
  340.     *((int *) v->addr) = x;
  341.     break;
  342.       case VAR_MAYBE:
  343.     *((int *) v->addr) = parse_yesnoask ("ask");
  344.     break;
  345.       case VAR_INTEGER:
  346.     if (n == SET_NEW_FILE_MODE)
  347.         x = parse_number (8, "octal mode", nil);
  348.     else
  349.         x = parse_number (10, "decimal number", nil);
  350.     confirm ();
  351.     *((int *) v->addr) = x;
  352.     if (n == SET_AUTOWRAP_COLUMN)
  353.         cmcsb._cmwrp = autowrap_column;
  354.     if (n == SET_NEW_FILE_MODE)
  355.         umask (~(new_file_mode&04777));
  356.     break;
  357.       case VAR_ADDRLIST:
  358.     dangling = nil;
  359.     parse_addresses((addresslist *)v->addr);
  360.     break;
  361.       case VAR_KEYLIST:
  362.     dangling = *((char **) v->addr);
  363.     *((char ***) v->addr) = parse_keylist (0, 0, "header keyword");
  364.     break;
  365.       case VAR_DIRECTORY:
  366.     p = parse_directory ("directory name", v->addr);
  367.     strcpy (v->addr, p);
  368.     break;
  369.       case VAR_FILES:
  370.     dangling = *((char **) v->addr);
  371.     *((char ***) v->addr) = parse_filelist (0, 0, "filename", true);
  372.     break;
  373.       case VAR_FILE:
  374.     p = parse_input_file ("filename", v->addr, false);
  375.     confirm();
  376.     strcpy(v->addr, p);
  377.     break;
  378.       case VAR_OFILE:
  379.     p = parse_output_file("filename", v->addr, true);
  380.     confirm();
  381.     strcpy(v->addr, p);
  382.     if (n == SET_MAIL_FILE) {    /* changed their primary mail file */
  383.         if (cf != NULL) {
  384.         if (strcmp(cf->filename, p) == 0)
  385.             cf->flags |= MF_MAILBOX; /* primary mailbox? */
  386.         else
  387.             cf->flags &= ~MF_MAILBOX; /* not any more */
  388.         }
  389.     }
  390.     break;
  391.       case VAR_CMDARGS:
  392.     {
  393.         char **cp;
  394.         
  395.         p = parse_text ("text string", nil);
  396.         for (cp = *((char ***) v->addr); cp && *cp; cp++)
  397.             safe_free (*cp);
  398.         safe_free (*((char ***) v->addr));
  399.         *((char ***) v->addr) = split_args(p);    
  400.     }
  401.     break;
  402.       case VAR_COMMAND: /* should parse for an executable file, but too slow */
  403.       case VAR_TEXT:
  404.     p = parse_text ("text string", nil);
  405.     if (strlen (p) >= v->size)
  406.         cmerr ("Variable \"%s\" can be no more than %d characters long",
  407.            v->name, v->size - 1);
  408.     strcpy (v->addr, p);
  409.     break;
  410.       case VAR_PROMPT:
  411.     p = (char *) parse_prompt("string to prompt with");
  412.     if (strlen(p) >= v->size)
  413.         cmerr ("Variable \"%s\" can be no more than %d characters long",
  414.            v->name, v->size -1);
  415.     strcpy (v->addr, p);
  416.     break;
  417.       case VAR_QUOTEDSTR:
  418.     p = parse_quoted("quoted string", nil);
  419.     confirm();
  420.     if (strlen (p) >= v->size)
  421.         cmerr ("Variable \"%s\" can be no more than %d characters long",
  422.            v->name, v->size - 1);
  423.     strcpy (v->addr, p);
  424.     break;
  425.       case VAR_USERNAME:
  426.     p = parse_username ("username", user_name);
  427.     confirm();
  428.     if (n == SET_USER_NAME) {
  429.       struct passwd *p1,*getpwnam();
  430.       p1 = getpwnam(p);
  431.       if (p1 == NULL || p1->pw_uid != getuid())
  432.           cmerr("Username \"%s\" does not match your uid", p1->pw_name);
  433.       sethome(p);
  434.         }
  435.     strcpy(v->addr, p);
  436.     break;
  437.       case VAR_KEYWORDS:
  438.     p = parse_keyword(((setkey *)v->addr)->keytab, FALSE);
  439.     if (p != NULL) {
  440.         confirm();
  441.         strcpy(((setkey *)v->addr)->current,p);
  442.     }
  443.     else
  444.         ((setkey *)v->addr)->current[0] = '\0'; /* no default */
  445.     break;
  446.       case VAR_CMDKEYS:    {
  447.     fdb *fdbs;
  448.     static fdb cfmfdb = { _CMCFM, CM_SDH|CM_NLH, NULL, NULL, 
  449.                 "confirm to unset", NULL, NULL, NULL };
  450.  
  451.     switch (n) {
  452.     case SET_DEFAULT_READ_COMMAND:
  453.       fdbs = fdbchn (&mm_read_fdb_abbr, &mm_read_fdb_1, 
  454.              &mm_read_fdb_2, &mm_read_fdb_3, &mm_read_fdb_4, 
  455.              &mm_read_fdb_5, &mm_read_fdb_6, &mm_read_fdb_7, 
  456.              &mm_read_fdb_inv, 
  457.              &cfmfdb, nil);
  458.  
  459.       break;
  460.     case SET_DEFAULT_SEND_COMMAND:
  461.       fdbs = fdbchn (&mm_send_fdb_abbr, &mm_send_fdb_1, 
  462.              &mm_send_fdb_2, &mm_send_fdb_3, &mm_send_fdb_4, 
  463.              &mm_send_fdb_5, &mm_send_fdb_inv, 
  464.              &cfmfdb, nil);
  465.       break;
  466.     }
  467.     parse (fdbs, &pv, &used);
  468.     if (used == &cfmfdb)
  469.       *v->addr = '\0';
  470.     else {
  471.       confirm();
  472.       strcpy (v->addr, ((keywrd *) pv._pvkey)->_kwkwd);
  473.     }
  474.     break;                /* dont lose this! */
  475.       }
  476.       case VAR_ALIAS:
  477.     cmd_define(CMD_DEFINE);
  478.     break;
  479.       default:
  480.     printf ("set_variable called to set unknown variable type %d\n");
  481.     }
  482.     v->changed = TRUE;
  483.     if (dangling) {
  484.     safe_free (dangling);
  485.     }
  486.     return true;
  487. }
  488.  
  489. int
  490. show_variable (fp, n, verbose)
  491. FILE *fp;
  492. int n, verbose;
  493. {
  494.     char **ap;
  495.     variable *v = &set_variables[n];
  496.     int i;
  497.  
  498.     if (verbose && n != SET_MAIL_ALIASES)
  499.     fprintf (fp, "set %s ", v->name);
  500.     switch (set_variables[n].type) {
  501.       case VAR_BOOLEAN:
  502.     fprintf (fp, "%s", (*((int *) v->addr) ? "yes" : "no"));
  503.     break;
  504.       case VAR_MAYBE:
  505.     switch (*((int *) v->addr)) {
  506.       case SET_NEVER:
  507.         fprintf (fp, "never");
  508.         break;
  509.       case SET_ALWAYS:
  510.         fprintf (fp, "always");
  511.         break;
  512.       case SET_ASK:
  513.         fprintf (fp, "ask");
  514.         break;
  515.     }
  516.     break;
  517.       case VAR_INTEGER:
  518.     if (n == SET_NEW_FILE_MODE)
  519.         fprintf (fp, "%o", *((int *) v->addr));
  520.     else
  521.         fprintf (fp, "%d", *((int *) v->addr));
  522.     break;
  523.       case VAR_TEXT:
  524.       case VAR_USERNAME:
  525.       case VAR_CMDKEYS:
  526.     fprintf (fp, "%s", v->addr);
  527.     break;
  528.       case VAR_DIRECTORY:
  529.       case VAR_COMMAND:
  530.       case VAR_FILE:
  531.       case VAR_OFILE:
  532.     show_filename (fp, v->addr, true);
  533.     break;
  534.       case VAR_QUOTEDSTR:
  535.       case VAR_PROMPT:
  536.     fprintf(fp, "\"%s\"", v->addr);
  537.     break;
  538.       case VAR_FILES:            /* these aren't comma-separated */
  539.     for (ap = *((char ***) v->addr); ap && *ap; ap++) {
  540.         show_filename (fp, *ap,true);
  541.         if (*(ap+1))
  542.         putc (' ',fp);
  543.     }
  544.     break;
  545.       case VAR_KEYLIST:
  546.     for (ap = *((char ***) v->addr); ap && *ap; ap++)
  547.         fprintf (fp, "%s%s", *ap, (*(ap+1) ? ", " : ""));
  548.     break;
  549.       case VAR_CMDARGS:
  550.     for (ap = *((char ***) v->addr); ap && *ap; ap++)
  551.         fprintf (fp, "%s ", *ap);
  552.     break;
  553.       case VAR_ADDRLIST:
  554.     disp_addresses(fp, nil, v->addr, true, false, false, true);
  555.     break;
  556.       case VAR_KEYWORDS:
  557.     fprintf(fp,"%s", ((setkey *)v->addr)->current);
  558.     break;
  559.       case VAR_ALIAS:
  560.     for(i = 0; i < mail_aliases.count; i++)
  561.         disp_alias(fp, i, true,true);
  562.     break;
  563.     }
  564.     if (verbose)
  565.     putc ('\n', fp);
  566.     return true;
  567. }
  568.  
  569. int
  570. cmd_set (n)
  571. int n;
  572. {
  573.     static fdb cfmfdb = { _CMCFM, CM_SDH, nil, nil, 
  574.                   "confirm to show all variable settings",
  575.                   nil, nil, nil };
  576.  
  577.     noise ("variable");
  578.     parse (fdbchn (&cfmfdb,&set_cmd_fdb, nil), &pv, &used);
  579.     if (used == &cfmfdb)
  580.     show_all_variables(cmcsb._cmoj ? cmcsb._cmoj : stdout);
  581.     else
  582.     (void) set_variable (pv._pvint);
  583.     return true;
  584. }
  585.  
  586. int
  587. cmd_show (n)
  588. int n;
  589. {
  590.     int i;
  591.     extern fdb aliasfdb;
  592.     FILE *out;                /* for output */
  593.  
  594.     noise ("settings");
  595.     
  596.     aliasfdb._cmdat = (pdat) mk_alias_keys();
  597.     aliasfdb._cmdef = nil;
  598.     parse (fdbchn(&cfm_fdb, &aliasfdb, &set_cmd_fdb, nil), &pv, &used);
  599.     out = cmcsb._cmoj ? cmcsb._cmoj : stdout;
  600.     if (used == &cfm_fdb) {
  601.     show_all_variables(out);
  602.     }
  603.     else if (used == &set_cmd_fdb) {
  604.     i = pv._pvint;
  605.     confirm ();
  606.     show_variable (out, i, true);
  607.     }
  608.     else {
  609.     i = pv._pvint;
  610.     confirm();
  611.     disp_alias(out, i, true,true);
  612.     }
  613.     return true;
  614. }
  615.  
  616. /*
  617.  * show_filename:
  618.  * show a filename, abbreviating to ~ where appropriate
  619.  */
  620. char *
  621. show_filename (fp, longname, disp)
  622. FILE *fp;
  623. char *longname;
  624. int disp;
  625. {
  626.     int len = strlen (HOME);
  627.     static char buf[100];
  628.     if ((strcmp(HOME, "/") != 0) &&    /* don't abbreviate "/" */
  629.     (strncmp (longname, HOME, len) == 0)) { /* something in homedir */
  630.     if (longname[len] != '\0')
  631.         sprintf (buf, "~%s", &longname[len]);
  632.     else                /* exactly homedir */
  633.         sprintf (buf, "~");
  634.     }
  635.     else
  636.     sprintf (buf, "%s", longname);
  637.     if (disp)
  638.     fprintf(fp,"%s",buf);
  639.     return(buf);
  640. }
  641.  
  642.  
  643. static char *
  644. tilde_expand(dir)
  645. char *dir;
  646. {
  647.   static char buf[MAXPATHLEN];
  648.   if (*dir != '~') return(dir);
  649.   strcpy(buf,HOME);
  650.   strcat(buf,&dir[1]);
  651.   return(buf);
  652. }
  653.  
  654.  
  655. /* The following routines handle a fast start up by directly reading
  656.  * junk in from an .mmfast file.  They are here instead of in init.c
  657.  * or doinit.c because the code there merely calls them.  Since they
  658.  * are, in a way, parsing commands, it makes partial sense to put them
  659.  * in here.  If fast init files turn out to be a bad idea (horrors!),
  660.  * then this code can be easily changed to something like what MM-20
  661.  * does (ie, a fast hacky text parser).
  662.  */
  663. #define fail(fp) {fclose(fp); return(false);}
  664. int
  665. read_fast_init_file()        /* Reads the fast init file */
  666. {
  667.   register int icount;        /* Number of guys we got */
  668.   int vindex;            /* Variable index--not register, guess why! */
  669.   int ccount;            /* Character count */
  670.   register char ** ap;        /* A pointer */
  671.   FILE *fp;
  672.   buffer fastname,        /* Fast init file name */
  673.        initname;        /* Regular init file name */
  674.   struct stat faststat,        /* struct to stat time of fast init file */
  675.             initstat;        /* Also to stat the init file */
  676.   char filetext[BUFSIZ];
  677.   char *sstr(),*name, *cp;
  678.   char **p,*tilde_expand(),*safe_strcpy();
  679.   int count,i;
  680.   variable *v;
  681.   addresslist *al,al1;
  682.   char *show_filename();
  683.   int vlen, olen;
  684.  
  685.   if (HOME == NULL)        /* Can't do much without a home */
  686.     return false;
  687.  
  688.   sprintf (initname, "%s/.mminit", HOME);
  689.   sprintf (fastname, "%s/.mmfast", HOME);
  690.   if (stat(fastname,&faststat) != 0)    /* Is the fast file even there? */
  691.     return false;        /* Not there, so can't read it */
  692.  
  693.   if (fast_init_file == SET_ASK)
  694.     if (!yesno("Fast init file exists -- read it? ", "yes"))
  695.       return (false);
  696.  
  697.   if (stat(initname,&initstat) == 0)    /* Is the init file even there? */
  698.       if (faststat.st_mtime <    /* Is the fast file older then the */
  699.       initstat.st_mtime)    /* fast file? */
  700.       return false;        /* The fast init file is out of date */
  701.  
  702.   fp = fopen(fastname, "r");
  703.  
  704.   if (fp == NULL)
  705.     return false;        /* Can't parse it if can't open it */
  706.  
  707.   vlen = strlen(mm_version);
  708. #ifdef FASTBIN
  709.   olen = strlen(OStype);
  710. #else
  711.   olen = -1;
  712. #endif
  713.  
  714.   if (fgets(filetext,vlen+olen+1+2,fp) == NULL) /* Chew newline */
  715.     return false;        /* It's bad if we can't read version string */
  716.  
  717.   if (strncmp(filetext, mm_version, vlen) != 0) /* Ignore newline */
  718.     return false;        /* Version has changed */
  719. #ifdef FASTBIN
  720.   if (strncmp(&filetext[vlen+1],OStype,olen) != 0) /* OSTYPE matters if */
  721.     return false;            /* binary fastfile */
  722. #endif  
  723.  
  724.   while (gnum(fp,&vindex)) {
  725.     v = &set_variables[vindex];
  726.     switch(v->type) {
  727.       case VAR_BOOLEAN:    /* Simple variables just want numbers */
  728.       case VAR_MAYBE:
  729.       case VAR_INTEGER:
  730.     if (!gnum(fp,v->addr)) fail(fp);
  731.     break;
  732.       case VAR_TEXT:        /* All text is counted */
  733.       case VAR_CMDKEYS:
  734.       case VAR_QUOTEDSTR:
  735.       case VAR_PROMPT:
  736.       case VAR_USERNAME:
  737.       case VAR_COMMAND:
  738.     if (!gsstr(fp, v->addr)) fail(fp);
  739.       break;
  740.       case VAR_DIRECTORY:
  741.       case VAR_FILE:
  742.       case VAR_OFILE:
  743.     if (!gstr(fp,&cp)) fail(fp);
  744.     strcpy(v->addr,
  745.            tilde_expand(cp)); /* De~ the filename */
  746.     safe_free(cp);
  747.     break;
  748.     
  749.       case VAR_FILES:
  750.     if (!gnum(fp,&count)) fail(fp);
  751.     if (count == 0) {
  752.         *((char ***) v->addr) = nil;
  753.         break;
  754.     }
  755.     p = (char **) malloc((count+1)*sizeof(char *));
  756.     *(char ***)v->addr = p;
  757.     for(i = 0; i < count; i++) {
  758.       char *cp,*cp1;
  759.       if (!gstr(fp,&cp)) fail(fp);
  760.       cp1 = tilde_expand(cp);
  761.       safe_free(cp);
  762.       p[i] = safe_strcpy(cp1);
  763.     }
  764.     p[count] = nil;
  765.     break;
  766.  
  767.       case VAR_KEYLIST:
  768.       case VAR_CMDARGS:
  769.     if (!gnum(fp,&count)) fail(fp);
  770.     if (count == 0) {
  771.       *((char ***) v->addr) = nil;
  772.       break;
  773.     }
  774.     p = (char **) malloc((count+1)*sizeof(char *));
  775.     *(char ***)v->addr = p;
  776.     for(i = 0; i < count; i++) {
  777.       char *cp;
  778.       if (!gstr(fp,&cp)) fail(fp);
  779.       p[i] = cp;
  780.     }
  781.     p[count] = nil;
  782.     break;
  783.  
  784.       case VAR_ADDRLIST:
  785.     if (!gnum(fp,&count)) fail(fp);
  786.     al = (addresslist *)v->addr;
  787.     al->first = al->last = nil;
  788.     for(i = 0; i < count; i++) {
  789.       char *cp;
  790.       int type;
  791.       if (!gnum(fp,&type)) fail(fp);
  792.       if (!gstr(fp,&cp)) fail(fp);
  793.       add_addresslist(al,cp,type);
  794.       safe_free(cp);
  795.     }
  796.     break;
  797.     
  798.       case VAR_ALIAS:
  799.     if (!gstr(fp,&name)) fail(fp);
  800.     if (!gnum(fp,&count)) fail(fp);
  801.     al1.first = al1.last = nil;
  802.     for(i = 0; i < count; i++) {
  803.       char *cp;
  804.       int type;
  805.       if (!gnum(fp,&type)) fail(fp);
  806.       if (!gstr(fp,&cp)) fail(fp);
  807.       add_addresslist(&al1,cp,type);
  808.       safe_free(cp);
  809.     }
  810.     set_alias(name,&al1,MA_USER);
  811.     break;        /* Read it real fast */
  812.     
  813.       case VAR_KEYWORDS:
  814.     if (!gstr(fp,&cp)) fail(fp);
  815.     strcpy(((setkey *)v->addr)->current, cp);
  816.     safe_free(cp);
  817.     break;
  818.     
  819.       default:        /* This is very bad and should not happen */
  820.     fprintf(stderr,"? %d,**UNKNOWN Variable index**\n",
  821.         vindex);
  822.     fail(fp);
  823.     break;
  824.       }                /* End of switch */
  825.     geol(fp);
  826.     v->changed = TRUE;
  827.   }
  828.   if (!feof(fp)) fail(fp);
  829.   fclose(fp);            /* Done parsing the file */
  830.   return true;
  831. }
  832.  
  833.  
  834. /* Much like the set command nonsense except that we write out the
  835.  * index of the variable in the set_variables array and follow it with
  836.  * the data in the variable.  We then use that integer to index into
  837.  * an array to set the data instead wasting time parsing.  This is
  838.  * pretty straightforward except for lists of objects.  All non-unary
  839.  * objects are preceeded by a length count.  Lists of objects are also
  840.  * preceeded by an object count.
  841.  */
  842.  
  843. int
  844. write_fast_init_file()        /* Writes the fast init file */
  845. {
  846.   register int n;        /* Current index in set_variables array */
  847.   char **ap;
  848.   variable * v;
  849.   char * shortname, *cp;
  850.   FILE *fp;
  851.   buffer filename;
  852.   int count;
  853.   addresslist *al;
  854.   addr_unit *a;
  855.  
  856.   if (HOME == NULL)        /* Can't do much without a home */
  857.    return false;
  858.  
  859.   sprintf (filename, "%s/.mmfast", HOME);
  860.   fp = fopen(filename, "w");
  861.  
  862. #ifdef FASTBIN
  863.   fprintf(fp,"%s,%s\n",mm_version, OStype); /* Stick out version and OSTYPE */
  864. #else
  865.   fprintf(fp,"%s\n",mm_version);    /* Stick out the version */
  866. #endif
  867.  
  868.   for (n=0,v = &set_variables[n]; /* Loop through all the variables */
  869.        n < (sizeof (set_variables) / sizeof (variable)); /* End of table */
  870.        n++,v = &set_variables[n]) {
  871.     if (!v->changed)
  872.       continue;
  873.     if (v->type != VAR_ALIAS)
  874.       pnum(fp,n);
  875.     switch (set_variables[n].type) {
  876.  
  877.       case VAR_BOOLEAN:        /* Simple variables just want numbers */
  878.       case VAR_MAYBE:
  879.       case VAR_INTEGER:
  880.     pnum(fp, *((int *)v->addr));
  881.     break;
  882.  
  883.       case VAR_TEXT:        /* All text is counted */
  884.       case VAR_CMDKEYS:
  885.       case VAR_QUOTEDSTR:
  886.       case VAR_PROMPT:
  887.       case VAR_USERNAME:
  888.       case VAR_COMMAND:
  889.     pstr(fp,v->addr);
  890.     break;
  891.  
  892.       case VAR_DIRECTORY:
  893.       case VAR_FILE:
  894.       case VAR_OFILE:
  895.     cp = show_filename(fp,v->addr,false);
  896.     pstr(fp,cp);
  897.     break;
  898.  
  899.       case VAR_FILES:
  900.     for (count=0,ap = *((char ***) v->addr); ap && *ap; ap++,count++);
  901.     pnum(fp,count);
  902.       for (ap = *((char ***) v->addr); ap && *ap; ap++) {
  903.         cp = show_filename(fp, *ap, false);
  904.         pstr(fp,cp);
  905.       }
  906.     break;
  907.  
  908.       case VAR_KEYLIST:
  909.       case VAR_CMDARGS:
  910.     for (count=0,ap = *((char ***) v->addr); ap && *ap; ap++,count++);
  911.     pnum(fp,count);
  912.     for (ap = *((char ***) v->addr); ap && *ap; ap++)
  913.       pstr(fp, *ap);
  914.     break;
  915.  
  916.       case VAR_ALIAS:            /* an alias */
  917.     for (count = 0; count < mail_aliases.count; count++) {
  918.       if (mail_aliases.aliases[count].type == MA_USER) { 
  919.         al = &mail_aliases.aliases[count].alias; /* save if user set */
  920.         pnum(fp,n);
  921.         if (al->first){
  922.           int naliases;
  923.           for(naliases = 0, a = al->first; 
  924.           a != nil;
  925.           naliases++, a = a->next );
  926.           pstr(fp,mail_aliases.aliases[count].name);
  927.           pnum(fp,naliases);
  928.           for(a = al->first; ; a = a->next) {
  929.         if (a->type == ADR_MLIST)
  930.           pnum(fp,ADR_LISTFILE);
  931.         else
  932.           pnum(fp,a->type);
  933.         pstr(fp,a->data);
  934.         if (a == al->last) break;
  935.           }
  936.         }
  937.         peol(fp);
  938.       }
  939.         }
  940.     break;
  941.       case VAR_ADDRLIST:
  942.     al = (addresslist *) v->addr;
  943.     for(count = 0, a = al->first; a != nil; count++, a = a->next );
  944.     pnum(fp, count);
  945.     if (al->first) {
  946.       for(a = al->first; ; a = a->next) {
  947.         if (a->type == ADR_MLIST)
  948.           pnum(fp,ADR_LISTFILE);
  949.         else
  950.           pnum(fp,a->type);
  951.         pstr(fp,a->data);
  952.         if (a == al->last) break;
  953.       }
  954.     }
  955.     break;
  956.       case VAR_KEYWORDS:
  957.     cp = ((setkey *)v->addr)->current;
  958.     pstr(fp,cp);
  959.     break;
  960.  
  961.  
  962.       default:            /* This is very bad and should not happen */
  963. /*    fprintf(fp,"%d,%d,**UNKNOWN**\n",n,set_variables[n].type);*/
  964.     break;
  965.       }
  966.     if (v->type != VAR_ALIAS)
  967.       peol(fp);
  968.   }
  969.   fflush(fp);            /* Get everything out of there */
  970.   fclose(fp);
  971.   return true;
  972. }
  973.  
  974.  
  975. pnum(fp, n)
  976. FILE *fp;
  977. int n;
  978. {
  979. #ifdef FASTBIN
  980.   int i;
  981.   char *cp = (char *)&n;
  982.   for(i = 0; i < sizeof(int); i++,cp++)
  983.     putc(*cp,fp);
  984. #else
  985.   fprintf(fp,"%d,",n);
  986. #endif
  987. }
  988.  
  989. pstr(fp, str)
  990. FILE *fp;
  991. char *str;
  992. {
  993.     int n = strlen(str);
  994.     pnum(fp,n);
  995. #ifdef FASTBIN
  996.     fprintf(fp,"%s",str);
  997. #else
  998.     fprintf(fp,"%s,",str);
  999. #endif
  1000. }
  1001.  
  1002. peol(fp)
  1003. FILE *fp;
  1004. {
  1005. #ifndef FASTBIN
  1006.     fprintf(fp,"\n");
  1007. #endif
  1008. }
  1009.  
  1010. int
  1011. gnum(fp,num)
  1012. FILE *fp;
  1013. int *num;
  1014. {
  1015.     int n;
  1016. #ifdef FASTBIN
  1017.     int i;
  1018.     int k;
  1019.     char *cp = (char *)&n;
  1020.  
  1021.     for(i = 0; i < sizeof(int); i++) {
  1022.       k = getc(fp);
  1023.       if (k == EOF) return(false);
  1024.       *cp++ = k;
  1025.     }
  1026.     *num = n;
  1027.     return(true);
  1028. #else
  1029.     if (fscanf(fp,"%d,",&n) != 1) return(false);
  1030.     *num = n;
  1031.     return(true);
  1032. #endif
  1033. }
  1034.  
  1035.  
  1036. int
  1037. gstr(fp,cp) 
  1038. FILE *fp;
  1039. char **cp;
  1040. {
  1041.     int n,c;
  1042.     char *buf;
  1043.  
  1044. #ifdef FASTBIN
  1045.     if (gnum(fp,&n) == false) return(false);
  1046.     buf = malloc(n+1);
  1047.     if (n != 0)
  1048.       if (fread(buf,sizeof(char),n,fp) <= 0) return(false);
  1049.     buf[n] = '\0';
  1050.     *cp = buf;
  1051.     return(true);
  1052. #else
  1053.     if (fscanf(fp,"%d,",&n) != 1) return(false);
  1054.     buf = malloc(n+1);
  1055.     if (n != 0)
  1056.       if (fread(buf,sizeof(char),n,fp) <= 0) return(false);
  1057.     c = getc(fp);
  1058.     if (c == EOF) return(false);
  1059.     if (c != ',') {
  1060.     ungetc(c,fp);
  1061.     return(false);
  1062.     }
  1063.     buf[n] = '\0';
  1064.     *cp = buf;
  1065.     return(true);
  1066. #endif
  1067. }
  1068.  
  1069.  
  1070. int
  1071. gsstr(fp,cp) 
  1072. FILE *fp;
  1073. char *cp;
  1074. {
  1075.     int n,c;
  1076.     char *buf;
  1077.  
  1078. #ifdef FASTBIN
  1079.     if (gnum(fp,&n) == false) return(false);
  1080.     if (n != 0)
  1081.       if (fread(cp,sizeof(char),n,fp) <= 0) return(false);
  1082.     cp[n] = '\0';
  1083.     return(true);
  1084. #else
  1085.     if (fscanf(fp,"%d,",&n) != 1) return(false);
  1086.     if (n != 0)
  1087.       if (fread(cp,sizeof(char),n,fp) <= 0) return(false);
  1088.     cp[n] = '\0';
  1089.     c = getc(fp);
  1090.     if (c == EOF) return(false);
  1091.     if (c != ',') {
  1092.     ungetc(c,fp);
  1093.     return(false);
  1094.     }
  1095.     return(true);
  1096. #endif
  1097. }
  1098.  
  1099. int 
  1100. geol(fp) 
  1101. FILE *fp;
  1102. {
  1103. #ifndef FASTBIN
  1104.     int c;
  1105.     c = getc(fp);
  1106.     if (c == EOF) return(false);
  1107.     if (c != '\n') {
  1108.     ungetc(c,fp);
  1109.     return(false);
  1110.     }
  1111. #endif
  1112.     return(true);
  1113. }
  1114.  
  1115. /*
  1116.  * split_args:
  1117.  * takes a string containing a command and splits it up into
  1118.  * individual arg's and returns a char ** (argv) pointing at them.
  1119.  * note: arguments in single quotes are taken literally.  The
  1120.  * backslash character makes the following character be taken literally.
  1121.  */
  1122.  
  1123. char **
  1124. split_args (str)
  1125. char *str;
  1126. {
  1127.     char *cp;
  1128.     char *temp = NULL;            /* temp buffer to build arguments */
  1129.     int i = 0;                /* current position in temp buffer */
  1130.     int count = 0;            /* number of slots in args[] */
  1131.     int anum = 0;            /* slots in use in args[] */
  1132.     char **args = NULL;            /* argument list to be returned */
  1133.  
  1134.     if (str == NULL)            /* null string, no args */
  1135.     return (NULL);
  1136.     if ((temp = (char *) malloc (strlen (str) + 1)) == NULL)
  1137.     return (NULL);
  1138.  
  1139.     cp = str;
  1140.     while (*cp) {            /* count number of spaces */
  1141.     if (isspace(*cp))        /* this should give us an */
  1142.         count++;            /* idea of the number of args */
  1143.     cp++;
  1144.     }
  1145.     count += 2;                /* and a couple more */
  1146.     /* get space for arg list */
  1147.     if ((args = (char **) malloc (count*sizeof(char *))) == NULL)
  1148.     return (NULL);
  1149.  
  1150.     cp = str;
  1151.     while (*cp) {            /* break up into args */
  1152.     while (*cp && isspace(*cp))    /* skip initial spaces */
  1153.         cp++;
  1154.     if (!*cp)
  1155.         break;            /* no more args */
  1156.  
  1157.     if (isquote(*cp)) {        /* starts with quote */
  1158.         cp++;            /* skip the quote */
  1159.         while (*cp && !isquote(*cp)) { /* till matching quote is found */
  1160.         if (isbackslash(*cp))
  1161.             cp++;        /* skip over the backslash */
  1162.         temp[i++] = *cp;
  1163.         cp++;
  1164.         }
  1165.         if (*cp)            /* string didn't end  */
  1166.         cp++;            /* skip the end quote */
  1167.     }
  1168.     else {                /* begins with something else */
  1169.         while (*cp && !isspace(*cp)) { /* go till end of word (space) */
  1170.         if (isbackslash(*cp))
  1171.             cp++;        /* skip over the backslash */
  1172.         temp[i++] = *cp;
  1173.         cp++;
  1174.         }
  1175.     }
  1176.     temp[i] = '\0';            /* tie off an arg */
  1177.  
  1178.     if (anum >= count) {        /* need more space? */
  1179.         if ((args = (char **) 
  1180.          realloc (args, (++count)*sizeof(char *))) == NULL)
  1181.         return (NULL);
  1182.     }
  1183.     if ((args[anum] = (char *) malloc (strlen(temp)+1)) == NULL) {
  1184.         anum--;            /* back up */
  1185.         while (anum >= 0)
  1186.         safe_free (args[anum--]);
  1187.         safe_free (args);
  1188.         return (NULL);
  1189.     }
  1190.     strcpy (args[anum++], temp);    /* save this argument */
  1191.     i = 0;                /* reset to beginning of buffer */
  1192.     }
  1193.     args[anum] = NULL;            /* tie off arg list */
  1194.     return (args);            /* return list */
  1195. }
  1196.  
  1197. /*
  1198.  * show_all_variables:
  1199.  * show the values of all variables
  1200.  */
  1201. show_all_variables(out)
  1202. FILE *out;
  1203. {
  1204.     int i,nv;
  1205.     FILE *fp, *more_pipe_open();    /* to pipe long output */
  1206.  
  1207.     nv = sizeof (set_variables) / sizeof (variable);
  1208.     if ((nv + mail_aliases.count) >= cmcsb._cmrmx)
  1209.     fp = more_pipe_open(out);    /* 1 line per variable or alias... */
  1210.     else
  1211.     fp = out;
  1212.     for (i = 0; i < nv; i++)
  1213.     if (i != SET_MAIL_ALIASES)
  1214.         show_variable (fp, i, true);
  1215.     for (i = 0; i < mail_aliases.count; i++)
  1216.     disp_alias (fp, i, true,true);
  1217.     if (fp == out)            /* not a pipe */
  1218.     fflush (fp);
  1219.     else
  1220.     more_pipe_close(fp);    /* really a pipe */
  1221. }
  1222.